|
To access the contents, click the chapter and section titles.
Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
(Publisher: John Wiley & Sons, Inc.)
Author(s): Rod Stephens
ISBN: 0471323519
Publication Date: 11/01/98
CHAPTER 5 Exposing Bugs
Chapter 1, Programming Philosophy, mentioned that defensive programming sometimes hides bugs. By continuing to execute safely even when an error occurs, a defensive subroutine covers up an error that might be a symptom of an important bug.
This chapter explains methods for making bugs obvious. By aggressively exposing bugs and potentially incorrect behaviors whenever they occur, a program can make bug finding and repair quick and easy.
Verify Arguments
Many errors occur because one routine calls another incorrectly. The caller passes the wrong kinds of arguments to the other routine, or it passes values that do not make sense. If the caller does not understand the routines arguments, it cannot use that routine correctly.
Even if it does receive a correct result while passing incorrect arguments to the routine, the caller is looking for trouble. Because the arguments are out of the normal range, the routine probably assumes the caller does not use those values. Another developer may later change the routines behavior when it receives these parameters thinking it will not hurt calling routines. In that case, the caller will stop working correctly.
This kind of bug can be hard to catch. Sometimes the bug may not appear until long after the called routine was changed. Even if it is immediately obvious that something is wrong, it is not apparent where the bug lies. A change to one routine has caused a bug in another that used to work properly before. Unless you are intimately familiar with the way in which the caller works, you may need to perform an extensive search to find the problem. When you do look at the caller, you will be prejudiced toward thinking the routine cannot be broken because it worked before.
The best time to catch this kind of error is the instant the incorrect arguments are first passed to the called routine. If the routine immediately reports an error, you can fix the caller quickly and easily.
Routines should verify that their arguments are correct before they start calculating with them. During project design, the routine should stop execution if it encounters an invalid argument. This action lets developers quickly find the problem and fix it.
Use Debug.Assert
If you are using Visual Basic 5 or 6, you can stop execution using Debug.Assert. The Debug.Assert statement checks a condition you specify and stops execution if the condition is False. The following code shows how a subroutine might verify that its variant arguments are strings. For example, the first Debug.Assert statement stops execution if the Boolean value VarType(param1) = vbString is False.
Make sure the parameters are strings.
Debug.Assert VarType(param1) = vbString
Debug.Assert VarType(param2) = vbString
Debug.Assert VarType(param3) = vbString
When you compile a program, all Debug statements including Debug.Assert statements are removed. The intent is to use these statements during development and testing, but then remove them before building the final application. Because the statements are not part of the compiled executable, the program can run faster.
Unfortunately, removing the Debug.Assert statements leaves the routine unprotected. If another subroutine passes incorrect arguments in the compiled executable, the program will try to continue executing. This may produce the wrong results.
Even worse, you probably have not tested the program thoroughly when incorrect arguments are passed into the routine because Debug.Assert usually stops them. There is no telling what the routine may do in that case.
Also Visual Basic 4 and earlier versions do not have a Debug.Assert statement. All of these facts conspire to make Debug.Assert a marginal solution.
Use Stop
You can obtain a result similar to a Debug.Assert statement using an If statement and the Stop command.
Make sure the parameters are strings.
If Not (VarType(param1) = vbString) Then Stop
If Not (VarType(param2) = vbString) Then Stop
If Not (VarType(param3) = vbString) Then Stop
These statements work in Visual Basic 4 and earlier versions. They also work in the compiled executable program. Unfortunately, when this code is compiled, the Stop command displays the rather uninformative message Stop statement encountered and then the program halts. The message does not tell developers where the Stop statement was encountered, gives no useful information to the user, and does not allow the program to trap and handle the error. That makes Stop statements and Assert statements equally ineffective in compiled programs.
One solution is to use a conditional compilation constant to determine the action the program should take. If DEBUG_MODE is True, the program uses If and Stop statements to verify the arguments correctness. If DEBUG_MODE is False, the routine raises an error for the calling routine to handle if the argument is invalid.
Set to False before compiling.
#Const DEBUG_MODE = True
:
Make sure the parameters are strings.
If Not (VarType(param1) = vbString) Then
#If DEBUG_MODE Then
Stop
#Else
Err.Raise err_INVALID_PARAMETER, _
MyProgram.MySubroutine, _
Parameter must be a string
#End If
End If
This method allows the program to handle the error properly whether or not it is compiled. It also allows you to examine the behavior of the program in both modes by simply changing the value of DEBUG_MODE. For example, you can set DEBUG_MODE to False and run the noncompiled version in the development environment to see how the program will behave when it is compiled. This can help you test the programs error handlers, a step often overlooked by developers.
This technique still has a few problems. First, it requires that you remember to change the value of DEBUG_MODE whenever you compile. This method is also quite verbose. It takes roughly nine times as much code to validate the parameters as the previous version.
The following code uses two techniques to address these issues. First, it uses the variable DebugMode instead of the constant DEBUG_MODE. The program sets the value of DebugMode when it starts and the variable is then available to the entire program.
|